package com.framework.service.common.impl;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.ds.ItemDataSource;
import com.baomidou.dynamic.datasource.toolkit.CryptoUtils;
import com.framework.common.enums.result.ResultEnum;
import com.framework.common.model.response.R;
import com.framework.common.util.dataSource.DataSourceEncUtil;
import com.framework.common.util.other.NumeralUtil;
import com.framework.common.util.redis.RedisKeyUtil;
import com.framework.mapper.common.DataSourceConfigMapper;
import com.framework.model.common.vo.DataSourceConfigVo;
import com.framework.model.system.vo.SystemUserVo;
import com.framework.service.base.BaseService;
import com.framework.service.common.DataSourceConfigService;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.sql.DataSource;

/**
 * @author 龘鵺
 * @version 1.0
 * @className com.framework.service.common.impl.DataSourceConfigServiceImpl
 * @description 数据源配置业务接口实现类
 * @datetime 2025-05-06 14:13:10
 */
@Service("dataSourceConfigServiceImpl")
public class DataSourceConfigServiceImpl extends BaseService implements DataSourceConfigService {
    private Logger log = LoggerFactory.getLogger(DataSourceConfigServiceImpl.class);
    @Autowired
    private DataSourceConfigMapper dataSourceConfigMapper;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private DefaultDataSourceCreator dataSourceCreator;


    /**
     * @param id 1 编号
     * @return com.framework.model.common.vo.DataSourceConfigVo
     * @title 根据编号查询数据源配置
     * @description 根据编号查询数据源配置
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    public DataSourceConfigVo getByIdParam(Long id) {
        DataSourceConfigVo row = new DataSourceConfigVo();
        row.setId(id);
        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        DataSourceConfigVo p = dataSourceConfigMapper.selectByParam(row);
        if (p == null) {
            return new DataSourceConfigVo();
        }
        return p;
    }

    /**
     * @param row 1 数据源配置类
     * @return java.util.List<com.framework.model.common.vo.DataSourceConfigVo>
     * @title 查询数据源配置集合
     * @description 查询数据源配置集合
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    public List<DataSourceConfigVo> findByList(DataSourceConfigVo row) {
        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        List<DataSourceConfigVo> list = dataSourceConfigMapper.findByList(row);
        return list;
    }

    /**
     * @param row 1 数据源配置类
     * @return com.framework.common.model.response.R
     * @title 分页查询数据源配置列表
     * @description 分页查询数据源配置列表
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    public R<?> findParamPageList(DataSourceConfigVo row) {
        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        int count = dataSourceConfigMapper.findPageListCount(row);
        if (count == NumeralUtil.POSITIVE_ZERO) {
            return R.ok();
        }
        List<DataSourceConfigVo> list = dataSourceConfigMapper.findPageList(row);
        return R.ok(list, count);
    }

    /**
     * @param row 1 数据源配置类
     * @return com.framework.common.model.response.R
     * @title 新增数据源配置
     * @description 新增数据源配置
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> save(DataSourceConfigVo row) throws Exception {
        String timeKey = RedisKeyUtil.getObjKey("DATA_SOURCE_CONFIG_SAVE_KEY", "DATA_SOURCE_CONFIG_SAVE_KEY", "save");
        long expireNum = redisUtil.getExpire(timeKey);
        if (expireNum > NumeralUtil.POSITIVE_ZERO) {
            return R.fail("操作频繁,请" + expireNum + "秒后重试!");
        }
        if (DataSourceEncUtil.MASTER.equalsIgnoreCase(row.getCode())) {
            return R.fail("数据源编码禁止创建!");
        }
        int isExist = dataSourceConfigMapper.isExist(row);
        if (isExist > 0) {
            return R.fail(ResultEnum.CODE3000);
        }
        DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) dataSource;
        Map<String, DataSource> map = dynamicRoutingDataSource.getDataSources();
        if (map.containsKey(row.getCode())) {
            return R.fail(ResultEnum.CODE3000);
        }
        redisUtil.setString(timeKey, NumeralUtil.STRING_POSITIVE_ZERO, NumeralUtil.POSITIVE_THIRTY);
        SystemUserVo systemUserVo = getUser();
        Long userId = systemUserVo.getId();
        Date date = new Date();
        row.setCreateId(userId);
        row.setCreateTime(date);
        row.setOperaterId(userId);
        row.setOperaterTime(date);
        row.setOperaterStatus(NumeralUtil.POSITIVE_ONE);
        row.setAccount(CryptoUtils.encrypt(DataSourceEncUtil.publicKey, row.getAccount()));
        row.setPassword(CryptoUtils.encrypt(DataSourceEncUtil.publicKey, row.getPassword()));
//        row.setConnectAddress(CryptoUtils.encrypt(DataSourceEncUtil.publicKey, row.getConnectAddress()));
        //需要处理数据源存在的情况，新增数据源的话需要存进连接池。
        int num = dataSourceConfigMapper.insertSelective(row);
        // 动态注册数据源
        if (num > NumeralUtil.POSITIVE_ZERO && row.getEnableStatus().intValue() == NumeralUtil.POSITIVE_ONE && !map.containsKey(row.getCode())) {
            // 动态注册数据源
            dynamicRoutingDataSource.addDataSource(row.getCode(), getDataSource(row));
        }
        return R.ok();
    }

    /**
     * @param row 1 数据源配置类
     * @return com.framework.common.model.response.R
     * @title 编辑数据源配置
     * @description 编辑数据源配置
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> edit(DataSourceConfigVo row) throws Exception {
        String timeKey = RedisKeyUtil.getObjKey("DATA_SOURCE_CONFIG_EDIT_KEY", "DATA_SOURCE_CONFIG_EDIT_KEY", row.getId().toString());
        long expireNum = redisUtil.getExpire(timeKey);
        if (expireNum > NumeralUtil.POSITIVE_ZERO) {
            return R.fail("操作频繁,请" + expireNum + "秒后重试!");
        }
        if (DataSourceEncUtil.MASTER.equalsIgnoreCase(row.getCode())) {
            return R.fail("数据源编码禁止创建!");
        }
        int isExist = dataSourceConfigMapper.isExist(row);
        if (isExist > 0) {
            return R.fail(ResultEnum.CODE3000);
        }
        redisUtil.setString(timeKey, NumeralUtil.STRING_POSITIVE_ZERO, NumeralUtil.POSITIVE_THIRTY);
        DataSourceConfigVo queryParam = new DataSourceConfigVo();
        queryParam.setId(row.getId());
        queryParam.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        queryParam = dataSourceConfigMapper.selectByRow(queryParam);
        if (queryParam == null) {
            return R.fail("编辑信息不存在!");
        }
        DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) dataSource;
        Map<String, DataSource> map = dynamicRoutingDataSource.getDataSources();
        if (queryParam.getId().longValue() != row.getId().longValue() && map.containsKey(row.getCode())) {
            return R.fail(ResultEnum.CODE3000);
        }
        if (StringUtils.isNotEmpty(row.getAccount())) {
            row.setAccount(CryptoUtils.encrypt(DataSourceEncUtil.publicKey, row.getAccount()));
        }
        if (StringUtils.isNotEmpty(row.getPassword())) {
            row.setPassword(CryptoUtils.encrypt(DataSourceEncUtil.publicKey, row.getPassword()));
        }
//        row.setConnectAddress(CryptoUtils.encrypt(DataSourceEncUtil.publicKey, row.getConnectAddress()));
        SystemUserVo systemUserVo = getUser();
        Long userId = systemUserVo.getId();
        Date date = new Date();
        row.setOperaterTime(date);
        row.setOperaterId(userId);
        row.setOperaterStatus(NumeralUtil.POSITIVE_TWO);
        int num = dataSourceConfigMapper.updateByPrimaryKeySelective(row);
        //需要处理数据源存在的情况，修改数据源的话需要把最新参数存进连接池。
        if (StringUtils.isEmpty(row.getAccount())) {
            row.setAccount(queryParam.getAccount());
        }
        if (StringUtils.isEmpty(row.getPassword())) {
            row.setPassword(queryParam.getPassword());
        }
        if (queryParam.getCode().equals(row.getCode())) {
            if (num > NumeralUtil.POSITIVE_ZERO &&
                    row.getEnableStatus().intValue() == NumeralUtil.POSITIVE_TWO && map.containsKey(row.getCode())) {
                // 动态删除数据源
                dynamicRoutingDataSource.removeDataSource(row.getCode());
            } else if (num > NumeralUtil.POSITIVE_ZERO && !map.containsKey(row.getCode())) {
                // 动态注册数据源
                dynamicRoutingDataSource.addDataSource(row.getCode(), getDataSource(row));
            }
            return R.ok();
        }
        // 动态删除数据源
        if (num > NumeralUtil.POSITIVE_ZERO && map.containsKey(queryParam.getCode())) {
            // 动态删除数据源
            dynamicRoutingDataSource.removeDataSource(queryParam.getCode());
        }
        // 动态注册数据源
        if (num > NumeralUtil.POSITIVE_ZERO && row.getEnableStatus().intValue() == NumeralUtil.POSITIVE_ONE && !map.containsKey(row.getCode())) {
            // 动态注册数据源
            dynamicRoutingDataSource.addDataSource(row.getCode(), getDataSource(row));
        }
        return R.ok();
    }

    /**
     * @param id 1 编号
     * @return com.framework.common.model.response.R
     * @title 删除数据源配置
     * @description 删除数据源配置
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> delete(Long id) {
        String timeKey = RedisKeyUtil.getObjKey("DATA_SOURCE_CONFIG_DEL_KEY", "DATA_SOURCE_CONFIG_DEL_KEY", id.toString());
        long expireNum = redisUtil.getExpire(timeKey);
        if (expireNum > NumeralUtil.POSITIVE_ZERO) {
            return R.fail("操作频繁,请" + expireNum + "秒后重试!");
        }

        DataSourceConfigVo queryParam = new DataSourceConfigVo();
        queryParam.setId(id);
        queryParam.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        queryParam = dataSourceConfigMapper.selectByRow(queryParam);
        if (queryParam == null) {
            return R.fail("删除信息不存在!");
        }
        redisUtil.setString(timeKey, NumeralUtil.STRING_POSITIVE_ZERO, NumeralUtil.POSITIVE_THIRTY);
        DataSourceConfigVo row = new DataSourceConfigVo();
        Date date = new Date();
        SystemUserVo systemUserVo = getUser();
        Long userId = systemUserVo.getId();
        row.setId(id);
        row.setOperaterTime(date);
        row.setOperaterId(userId);
        row.setOperaterStatus(NumeralUtil.NEGATIVE_ONE);
        //需要处理数据源存在的情况，存在的话需要移除。
        int num = dataSourceConfigMapper.delete(row);
        DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) dataSource;
        Map<String, DataSource> map = dynamicRoutingDataSource.getDataSources();
        if (num > NumeralUtil.POSITIVE_ZERO && map.containsKey(queryParam.getCode())) {
            // 动态删除数据源
            dynamicRoutingDataSource.removeDataSource(queryParam.getCode());
        }
        return R.ok();
    }

    /**
     * @param idList 1 编号集合
     * @return com.framework.common.model.response.R
     * @title 批量删除数据源配置
     * @description 批量删除数据源配置
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> batchDeleteList(List<Long> idList) {
        DataSourceConfigVo row = new DataSourceConfigVo();
        SystemUserVo systemUserVo = getUser();
        Long userId = systemUserVo.getId();
        Date date = new Date();
        row.setIdList(idList);
        row.setOperaterTime(date);
        row.setOperaterId(userId);
        row.setOperaterStatus(NumeralUtil.NEGATIVE_ONE);
        //dataSourceConfigMapper.deleteList(row);
        return R.ok();
    }

    /**
     * @param row 1 数据源配置视图类
     * @return javax.sql.DataSource
     * @title 构建数据源属性
     * @description 构建数据源属性
     * @author 龘鵺
     * @datetime 2025-05-06 18:01:06
     */
    private DataSource getDataSource(DataSourceConfigVo row) {
        // 构建数据源属性
        DataSourceProperty property = new DataSourceProperty();
        property.setPoolName(row.getName());
        property.setUrl(row.getConnectAddress());
        property.setUsername(DataSourceEncUtil.getEnc(row.getAccount()));
        property.setPassword(DataSourceEncUtil.getEnc(row.getPassword()));
        property.setDriverClassName(row.getDriverClass());
        // 开启懒加载。避免一次性申请太多连接
        property.setLazy(true);
        // 动态注册数据源
        DataSource dataSource = dataSourceCreator.createDataSource(property);
        return dataSource;
    }

    /**
     * @param id 1 编号
     * @return com.framework.common.model.response.R
     * @title 启用|禁用，数据源配置
     * @description 启用|禁用，数据源配置
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> enable(Long id) {
        String timeKey = RedisKeyUtil.getObjKey("DATA_SOURCE_CONFIG_ENABLE_KEY", "DATA_SOURCE_CONFIG_ENABLE_KEY", id.toString());
        long expireNum = redisUtil.getExpire(timeKey);
        if (expireNum > NumeralUtil.POSITIVE_ZERO) {
            return R.fail("操作频繁,请" + expireNum + "秒后重试!");
        }
        DataSourceConfigVo row = new DataSourceConfigVo();
        SystemUserVo systemUserVo = getUser();
        Long userId = systemUserVo.getId();
        row.setId(id);
        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ZERO);
        row = dataSourceConfigMapper.selectByParam(row);
        if (row == null) {
            return R.fail("信息不存在!");
        }
        redisUtil.setString(timeKey, NumeralUtil.STRING_POSITIVE_ZERO, NumeralUtil.POSITIVE_THIRTY);
        Date date = new Date();
        DataSourceConfigVo updateRow = new DataSourceConfigVo();
        updateRow.setId(id);
        updateRow.setOperaterId(userId);
        updateRow.setOperaterTime(date);
        updateRow.setOperaterStatus(NumeralUtil.POSITIVE_TWO);
        updateRow.setEnableStatus(row.getEnableStatus().intValue() == NumeralUtil.POSITIVE_TWO ? NumeralUtil.POSITIVE_ONE : NumeralUtil.POSITIVE_TWO);
        int num = dataSourceConfigMapper.updateByPrimaryKeySelective(updateRow);
        DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) dataSource;
        Map<String, DataSource> map = dynamicRoutingDataSource.getDataSources();
        if (num > NumeralUtil.POSITIVE_ZERO && updateRow.getEnableStatus().intValue() == NumeralUtil.POSITIVE_TWO && map.containsKey(row.getCode())) {
            // 动态删除数据源
            dynamicRoutingDataSource.removeDataSource(row.getCode());
        } else if (num > NumeralUtil.POSITIVE_ZERO && !map.containsKey(row.getCode())) {
            // 动态注册数据源
            dynamicRoutingDataSource.addDataSource(row.getCode(), getDataSource(row));
        }
        return R.ok();
    }

    /**
     * @return com.framework.common.model.response.R
     * @title 查询使用数据库连接信息
     * @description 查询使用数据库连接信息
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     */
    @Override
    public R<?> findByDataSourceList() {
        DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) dataSource;
        Map<String, DataSource> map = dynamicRoutingDataSource.getDataSources();
        List<Map> list = new ArrayList<>(map.size());
        for (String item : map.keySet()) {
            Map<String, String> value = new HashMap<>(NumeralUtil.POSITIVE_TWO);
            ItemDataSource dataSource = (ItemDataSource) map.get(item);
            value.put("name", dataSource.getName());
            value.put("code", item);
            list.add(value);
        }
        return R.ok(list);
    }

    /**
     * @return com.framework.common.model.response.R
     * @title 重置所有数据库连接
     * @description 重置所有数据库连接
     * @author 龘鵺
     * @datetime 2025-05-06 14:13:10
     * @version 1.0
     */
    @Override
    public R<?> reset() {
        String timeKey = RedisKeyUtil.getObjKey("DATA_SOURCE_CONFIG_RESET_KEY", "DATA_SOURCE_CONFIG_RESET_KEY", "reset");
        long expireNum = redisUtil.getExpire(timeKey);
        if (expireNum > NumeralUtil.POSITIVE_ZERO) {
            return R.fail("操作频繁,请" + expireNum + "秒后重试!");
        }
        redisUtil.setString(timeKey, NumeralUtil.STRING_POSITIVE_ZERO, NumeralUtil.POSITIVE_ONE_HUNDRED_EIGHT);
        DataSourceConfigVo row = new DataSourceConfigVo();
//        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        List<DataSourceConfigVo> dataSourceConfigVoList = dataSourceConfigMapper.findByList(row);
        if (dataSourceConfigVoList.size() == NumeralUtil.POSITIVE_ZERO) {
            return R.ok();
        }
        DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) dataSource;
        Map<String, DataSource> map = dynamicRoutingDataSource.getDataSources();
        for (DataSourceConfigVo item : dataSourceConfigVoList) {
            if (DataSourceEncUtil.MASTER.equalsIgnoreCase(row.getCode())) {
                continue;
            }
            if (map.containsKey(item.getCode())) {
                // 动态删除数据源
                dynamicRoutingDataSource.removeDataSource(item.getCode());
            }
            if (item.getEnableStatus().intValue() == NumeralUtil.POSITIVE_ONE && item.getOperaterStatus() > NumeralUtil.POSITIVE_ZERO) {
                // 动态注册数据源
                dynamicRoutingDataSource.addDataSource(item.getCode(), getDataSource(item));
            }
        }
        return R.ok();
    }
}